package com.ffcs.crmd.tsp.core.netty;

import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.api.netty.INettyChannelEventListener;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.netty.NettyEvent;

/**
 * 
 * 功能说明:netty事件处理者
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class NettyEventExecuter extends Thread {
    
    /**
     * 日志
     */
    private static final Logger             LOG        = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 是否关闭
     */
    private volatile boolean                shutdown   = false;
    
    /**
     * 事件缓冲队列
     */
    private LinkedBlockingQueue<NettyEvent> eventQueue = new LinkedBlockingQueue<NettyEvent>();
    
    /**
     * 通道事件监听者
     */
    private INettyChannelEventListener      channelEventListener;
    
    public NettyEventExecuter(INettyChannelEventListener channelEventListener, String name) {
        this.setName(name);
        this.channelEventListener = channelEventListener;
    }
    
    public void putNettyEvent(final NettyEvent event) {
        try {
            this.eventQueue.put(event);
            LOG.debug("NETTY-COMMON: will to add a netty event success channel[{}] type[{}] size=[{}]", event.getChannel(), event.getType(), eventQueue.size());
        } catch (InterruptedException e) {
            LOG.warn("NETTY-COMMON: add netty event fail because is interrupted. [{}].", eventQueue.size());
        }
    }
    
    @Override
    public void run() {
        while (!shutdown) {
            try {
                NettyEvent event = this.eventQueue.take();
                LOG.debug("NETTY-COMMON: take a netty event type=[{}] addr=[{}] channel=[{}] total size=[{}].", 
                    event.getType(), event.getRemoteAddr(), event.getChannel(), eventQueue.size());
                switch (event.getType()) {
                    case IDLE:
                        channelEventListener.onChannelIdle(event.getRemoteAddr(), event.getChannel());
                        break;
                    case CLOSE:
                        channelEventListener.onChannelClose(event.getRemoteAddr(), event.getChannel());
                        break;
                    case CONNECT:
                        break;
                    case EXCEPTION:
                        channelEventListener.onChannelException(event.getRemoteAddr(), event.getChannel());
                        break;
                    default:
                        break;
                }
            } catch (Throwable e) {
                LOG.warn("NETTY-COMMON: Dealing with netty events exception:", e);
            }
        }
    }
    
    /**
     * 
     * 功能说明:关闭
     *
     */
    public void shutdown() {
        shutdown = true;
        interrupt();
    }

}
